﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using CronusModel;
using Cronus.ViewModel.Data;

namespace Cronus.ViewModel
{
    /// <summary>
    /// Provides an interface to query the projects table in the data model.
    /// </summary>
    internal class QueryProjectInformation
    {
        //*** Constants ***//
        //*** Static ***//
        //*** Member Variables ***//
        private DataModel _DataModel;

        //*** Properties ***//
        //*** Constructors ***//
        internal QueryProjectInformation(DataModel aDataModel)
        {
            _DataModel = aDataModel;
        }

        //*** Abstract Methods ***//
        //*** Methods ***//
        /// <summary>
        /// Returns a collection of all projects in the data model.
        /// </summary>
        /// <returns>Enumerable collection of projects in the data model.</returns>
        internal IEnumerable<CronusData.ProjectsRow> GetAllProjects()
        {
            IEnumerable<CronusData.ProjectsRow> allProjects = null;

            // Query the table, but don't set up any conditions on it.
            allProjects = from aProject in _DataModel.ProjectsTable
                          select aProject;
            return allProjects;
        }

        /// <summary>
        /// Queries the dataset to determine if a project with the given name exists.
        /// </summary>
        /// <param name="strProjectName">Name to query on.</param>
        /// <returns>TRUE if the project exists; FALSE otherwise.</returns>
        internal bool DoesProjectAlreadyExist(string strProjectName)
        {
            return (null != GetProjectWithName(strProjectName));
        }

        /// <summary>
        /// Queries the dataset for a project with the given name.  If the project doesn't exist,
        /// NULL is returned.
        /// </summary>
        /// <param name="strProjectName">The project name to query on.</param>
        /// <returns>Project with the give name, if it exists; NULL otherwise.</returns>
        internal Project GetProjectWithName(string strProjectName)
        {
            IEnumerable<CronusData.ProjectsRow> allProjectsWithName = from aProject in _DataModel.ProjectsTable
                                                                      where aProject.Name == strProjectName
                                                                      select aProject;
            // If a project exists, create an adapter from the first one.
            Project aProjectToReturn = null;
            foreach (CronusData.ProjectsRow aProjectRow in allProjectsWithName)
            {
                aProjectToReturn = new Project(aProjectRow);
                break;
            }
            return aProjectToReturn;
        }

        /// <summary>
        /// Returns a list of tasks that are associated with the given project name.  If the
        /// project name is empty or NULL, this returns a list of all tasks.
        /// </summary>
        /// <param name="strProjectName">Name of the project to query on.</param>
        /// <returns>List of tasks associated with the project name.</returns>
        internal IEnumerable<CronusData.TasksRow> GetTasksAssociatedWithProject(string strProjectName)
        {
            QueryTaskInformation aTaskQuery = new QueryTaskInformation(_DataModel);
            IEnumerable<CronusData.TasksRow> allTasks = aTaskQuery.GetAllTasks();
            IEnumerable<CronusData.TasksRow> allTasksInProject = null;

            // If a project name was specified, query for it.
            if ((null != strProjectName) && (String.Empty != strProjectName) &&
                (null != allTasks))
            {
                allTasksInProject = from aTask in allTasks
                                    where (aTask.ProjectsRow.Name == strProjectName)
                                    select aTask;
            }
            else
            {
                // No project specified, just use all of them.
                allTasksInProject = allTasks;
            }

            return allTasksInProject;
        }
        
        /// <summary>
        /// Query to determine how much time was spent on the given project.  If the project name
        /// is empty, all projects will be considered.
        /// </summary>
        /// <param name="strTaskName">Name of the project to query against.</param>
        /// <param name="aStartDate">Start period of the query.</param>
        /// <param name="anEndDate">End period of the query.</param>
        /// <returns>Total time spent logged against the project.</returns>
        internal TimeSpan GetProjectHoursInDateRange(string strProjectName, DateTime aStartDate, DateTime anEndDate)
        {
            // Local variables
            QueryActivityInformation anActivityQuery = new QueryActivityInformation(_DataModel);
            IEnumerable<CronusData.ActivitiesRow> allActivities = null;
            IEnumerable<CronusData.ActivitiesRow> allActivitiesWithProjectName = null;
            
            // Query for all of the activities in the time range specified.
            allActivities = anActivityQuery.GetActivitiesInDateRange(aStartDate, anEndDate);

            // Narrow down the resulting activities to ones associated with the given project name.
            if ((null != strProjectName) && (String.Empty != strProjectName) &&
                (null != allActivities))
            {
                allActivitiesWithProjectName = from anActivity in allActivities
                                               where (anActivity.TasksRow.ProjectsRow.Name == strProjectName)
                                               select anActivity;
            }
            else
            {
                // No project name was specified, just use the original query
                allActivitiesWithProjectName = allActivities;
            }

            // Sum up the total time spent on activites in this project
            TimeSpan allTimeSpent = new TimeSpan(0);
            if (null != allActivitiesWithProjectName)
            {
                foreach (CronusData.ActivitiesRow anActivity in allActivitiesWithProjectName)
                {
                    allTimeSpent += anActivity.Duration;
                }
            }
            return allTimeSpent;
        }
    }
}
